package com.ibeeking.found.content.b.rest.service.impl;

import com.ibeeking.found.common.config.prop.FileOssProp;
import com.ibeeking.found.common.enums.PublishStatusEnum;
import com.ibeeking.found.common.utils.DataUtils;
import com.ibeeking.found.common.utils.UrlUtils;
import com.ibeeking.found.common.utils.UserUtils;
import com.ibeeking.found.content.b.rest.service.IArticleAuthorService;
import com.ibeeking.found.content.b.rest.service.IArticleGroupService;
import com.ibeeking.found.content.b.rest.service.IArticleService;
import com.ibeeking.found.content.service.common.dos.ArticleDO;
import com.ibeeking.found.content.service.common.param.ArticleParam;
import com.ibeeking.found.content.service.common.query.ArticleAuthorQuery;
import com.ibeeking.found.content.service.common.query.ArticleGroupQuery;
import com.ibeeking.found.content.service.common.query.ArticlePageQuery;
import com.ibeeking.found.content.service.common.query.ArticleQuery;
import com.ibeeking.found.content.service.common.vo.ArticleAuthorVO;
import com.ibeeking.found.content.service.common.vo.ArticleCount;
import com.ibeeking.found.content.service.common.vo.ArticleGroupVO;
import com.ibeeking.found.content.service.common.vo.ArticleVO;
import com.ibeeking.found.content.service.mapper.ArticleMapper;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.data.ParamCheckUtils;
import com.ibeeking.nematos.utils.json.JsonUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @ClassName ArticleServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2022-02-18 14:11
 **/
@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, ArticleDO> implements IArticleService {

    @Resource
    private ArticleMapper articleMapper;
    @Resource
    private FileOssProp fileOssProp;
    @Resource
    private IArticleAuthorService articleAuthorServiceImpl;
    @Resource
    private IArticleGroupService articleGroupServiceImpl;

    @Override
    public List<ArticleVO> list(ArticleQuery articleQuery) {
        LambdaQueryWrapper<ArticleDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(articleQuery.getTitle()), ArticleDO::getTitle, articleQuery.getTitle());
        List<ArticleDO> articleDOs = articleMapper.selectList(queryWrapper);
        List<ArticleVO> articleVOS = JsonUtils.jsonToList(articleDOs, ArticleVO.class);
        wrapperVO(articleVOS);
        return articleVOS;
    }

    @Override
    public Page<ArticleVO> pageList(ArticlePageQuery articlePageQuery) {
        Page<ArticleDO> pages = articleMapper.selectPage(new Page<ArticleDO>(), new LambdaQueryWrapper<ArticleDO>()
                .eq(articlePageQuery.getPublishStatus() != null, ArticleDO::getPublishStatus, articlePageQuery.getPublishStatus())
                .eq(articlePageQuery.getGroupId() != null, ArticleDO::getGroupId, articlePageQuery.getGroupId())
                .eq(articlePageQuery.getAuthorId() != null, ArticleDO::getAuthorId, articlePageQuery.getAuthorId())
                .like(StringUtils.isNotBlank(articlePageQuery.getTitle()), ArticleDO::getTitle, articlePageQuery.getTitle())
                .ge(StringUtils.isNotBlank(articlePageQuery.getCreateTimeStart()), ArticleDO::getCreateTime, articlePageQuery.getCreateTimeStart())
                .le(StringUtils.isNotBlank(articlePageQuery.getCreateTimeEnd()), ArticleDO::getCreateTime, articlePageQuery.getCreateTimeEnd())
        );
        Page<ArticleVO> articleVOPage = BeanUtil.convertPage(pages, ArticleVO.class);
        List<ArticleDO> doRecords = pages.getRecords();
        List<ArticleVO> articleVOS = JsonUtils.jsonToList(doRecords, ArticleVO.class);
        wrapperVO(articleVOS);
        articleVOPage.setRecords(articleVOS);
        return articleVOPage;
    }

    @Override
    public Boolean add(ArticleParam articleParam) {
        wrapperParam(articleParam);
        checkUnique(articleParam);
        ArticleDO articleDO = BeanUtil.convertBean(articleParam, ArticleDO.class);
        articleDO.setCreateBy(UserUtils.getUserId());
        articleDO.setCreateTime(LocalDateTime.now());
        articleDO.setModifyTime(LocalDateTime.now());
        articleDO.setPublishStatus(PublishStatusEnum.DISABLE.getValue());
        int count = articleMapper.insert(articleDO);
        if (count > 0) {
            Long id = articleDO.getId();
            ArticleDO upDo = new ArticleDO();
            upDo.setId(id);
            upDo.setPagePath("?id=" + id);
            articleMapper.updateById(upDo);
        }
        return count > 0;
    }

    @Override
    public Boolean modify(ArticleParam articleParam) {
        wrapperParam(articleParam);
        checkUnique(articleParam);
        ArticleDO articleDO = BeanUtil.convertBean(articleParam, ArticleDO.class);
        articleDO.setModifyBy(UserUtils.getUserId());
        articleDO.setModifyTime(LocalDateTime.now());
        return articleMapper.updateById(articleDO) > 0;
    }

    @Override
    public ArticleVO view(Long id) {
        ArticleDO articleDO = articleMapper.selectById(id);
        ArticleVO articleVO = JsonUtils.fromJson(articleDO, ArticleVO.class);
        wrapperVO(Collections3.newArrayList(articleVO));
        return articleVO;
    }

    @Override
    public Boolean changeStatus(Long id, Integer status) {
        ArticleDO articleDO = new ArticleDO();
        articleDO.setId(id);
        articleDO.setPublishStatus(status);
        articleDO.setModifyTime(LocalDateTime.now());
        if (PublishStatusEnum.ENABLE.getValue().equals(status)) {
            articleDO.setPublishTime(LocalDateTime.now());
        }
        return articleMapper.updateById(articleDO) > 0;
    }

    @Override
    public Boolean changePutTopStatus(Long id, Integer status) {
        ArticleDO articleDO = new ArticleDO();
        articleDO.setId(id);
        articleDO.setPutTopStatus(status);
        articleDO.setModifyTime(LocalDateTime.now());
        return articleMapper.updateById(articleDO) > 0;
    }


    @Override
    public Boolean del(Long id) {
        return articleMapper.deleteById(id) > 0;
    }

    @Override
    public List<ArticleCount> countByGroup(List<Long> groupIds) {
        QueryWrapper<ArticleDO> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .in(Collections3.isNotEmpty(groupIds), "group_id", groupIds)
                .select("count(1) as num, group_id as id")
                .groupBy(" group_id");
        List<Map<String, Object>> maps = articleMapper.selectMaps(queryWrapper);
        return JsonUtils.jsonToList(maps, ArticleCount.class);
    }

    @Override
    public List<ArticleCount> countByAuthor(List<Long> authorIds) {
        QueryWrapper<ArticleDO> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .in(Collections3.isNotEmpty(authorIds), "author_id", authorIds)
                .select("count(1) as num, author_id as id")
                .groupBy(" author_id");
        List<Map<String, Object>> maps = articleMapper.selectMaps(queryWrapper);
        return JsonUtils.jsonToList(maps, ArticleCount.class);
    }


    public void wrapperParam(ArticleParam param) {
        ParamCheckUtils.stringTrim(param);
        List<String> coverImgList = param.getCoverImgList();
        DataUtils.trueThrowException(param.getCoverImgType() == 1 && Collections3.size(coverImgList) > 1, "单图只能上传一张图片");
        coverImgList = coverImgList.stream().map(x -> UrlUtils.removeMallUrlDomainName(fileOssProp.getHost(), x)).collect(Collectors.toList());
        param.setCoverImgs(Collections3.join(coverImgList, ","));
    }

    public void wrapperVO(List<ArticleVO> vos) {
        if (Collections3.isEmpty(vos)) {
            return;
        }
        List<Long> authorIds = vos.stream().map(ArticleVO::getAuthorId).collect(Collectors.toList());
        List<Long> groupIds = vos.stream().map(ArticleVO::getGroupId).collect(Collectors.toList());
        List<ArticleAuthorVO> authorList = articleAuthorServiceImpl.list(new ArticleAuthorQuery().setIds(authorIds));
        Map<Long, String> authorMap = authorList.stream().collect(Collectors.toMap(ArticleAuthorVO::getId, ArticleAuthorVO::getNickname));
        List<ArticleGroupVO> groupList = articleGroupServiceImpl.list(new ArticleGroupQuery().setIds(groupIds));
        Map<Long, String> groupMap = groupList.stream().collect(Collectors.toMap(ArticleGroupVO::getId, ArticleGroupVO::getName));
        for (ArticleVO vo : vos) {
            String coverImgs = vo.getCoverImgs();
            if (StringUtils.isNotBlank(coverImgs)) {
                List<String> imgList = Collections3.newArrayList(StringUtils.split(coverImgs, ","));
                imgList = imgList.stream().map(x -> UrlUtils.addUrlDomainName(fileOssProp.getHost(), x)).collect(Collectors.toList());
                vo.setCoverImgList(imgList);
            }
            vo.setAuthorName(authorMap.get(vo.getAuthorId()));
            vo.setGroupName(groupMap.get(vo.getGroupId()));
        }
    }

    /**
     * 校验唯一性
     *
     * @param param
     */
    public void checkUnique(ArticleParam param) {
        LambdaQueryWrapper<ArticleDO> queryWrapper = new LambdaQueryWrapper<ArticleDO>()
                .ne(param.getId() != null, ArticleDO::getId, param.getId())
                .eq(StringUtils.isNotBlank(param.getTitle()), ArticleDO::getTitle, param.getTitle());
        List<ArticleDO> dos = articleMapper.selectList(queryWrapper);
        if (Collections3.isNotEmpty(dos)) {
            throw new BusinessException("已经存在相同标题的文章!");
        }
    }
}
